package zfbpay

import (
	"errors"
	"net/http"
	"strconv"

	"github.com/go-pay/gopay"
	"github.com/go-pay/gopay/alipay"
)

const (
	// TradeStatusTradeSuccess 支付成功
	TradeStatusTradeSuccess = "TRADE_SUCCESS"
	// TradeStatusTradeFinished 支付完成
	TradeStatusTradeFinished = "TRADE_FINISHED"
	// TradeStatusTradeFail 支付失败
	TradeStatusTradeFail = "TRADE_FAIL"
)

// WithAppID set alipay app id.
func WithAppID(appID string) Option {
	return func(p *PayClient) {
		p.appID = appID
	}
}

// WithPrivateKey set alipay private key.
func WithPrivateKey(privateKey string) Option {
	return func(p *PayClient) {
		p.privateKey = privateKey
	}
}

// WithPublicKey set alipay public key.
func WithPublicKey(publicKey string) Option {
	return func(p *PayClient) {
		p.publicKey = publicKey
	}
}

// SetAppID set alipay app id.
func SetAppID(id string) {
	appID = id
}

// SetPrivateKey set alipay private key.
func SetPrivateKey(priKey string) {
	privateKey = priKey
}

// SetPublicKey set alipay public key.
func SetPublicKey(pubKey string) {
	publicKey = pubKey
}

// SetIsProd set alipay is production env.
func SetIsProd(prod bool) {
	isProd = prod
}

// BuildBodyMap return BodyMap
func BuildBodyMap(kvs ...BodyMapKV) gopay.BodyMap {
	bm := make(gopay.BodyMap)
	for _, kv := range kvs {
		bm.Set(kv.Key, kv.Val)
	}
	return bm
}

// Validator 支付宝支付异步通知参数解析和验签
//
//	req：*http.Request
//	返回参数 notifyReq：通知的参数
//	返回参数 err：错误信息
func Validator(req *http.Request) (notifyReq gopay.BodyMap, err error) {
	notifyReq, err = alipay.ParseNotifyToBodyMap(req)
	if err != nil {
		return
	}

	ok, err := alipay.VerifySign(publicKey, notifyReq)
	if err != nil {
		return
	}

	if !ok {
		err = errors.New("alipay notify sign verify fail")
		return
	}

	return
}

// IsTradeSuccess 校验支付状态
func IsTradeSuccess(tradeStatus string) bool {
	return tradeStatus == TradeStatusTradeSuccess || tradeStatus == TradeStatusTradeFinished
}

// ParseAmount 解析支付金额
func ParseAmount(amount string) (int64, error) {
	// 金额单位为元, 转换为分
	priceFloat, err := strconv.ParseFloat(amount, 64)
	if err != nil {
		return 0, err
	}

	return int64(priceFloat * 100), nil
}
